package com.example.springbootsenior.RedisCache.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springbootsenior.RedisCache.entry.po.Employee;
import com.example.springbootsenior.RedisCache.mapper.EmployeeMapper;
import com.example.springbootsenior.RedisCache.service.EmployeeService;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;

/**
 * 视频地址：https://www.bilibili.com/video/BV1KW411F7oX?p=4
 * 自动注入了cacheManager，有些配置的属性在RedisCacheConfiguration配置类中配置了。
 *
 * @createDate 2021-11-18 21:23:00
 */
@Service("employeeService")
/**
 * 【公共属性配置】
 * 进行统一配置，不需要再每个方法上写了
 * 可以配置以下属性，例如：
 * key、keyGenerator、cacheManager
 * 如果方法上面也配置了，按照就近原则，以方法为准
 */
@CacheConfig(cacheNames = "emp")
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee>
        implements EmployeeService {
    @Resource
    EmployeeMapper employeeMapper;

    /**
     * 【注解中的公共属性】
     * cacheName/value:指定缓存组件的名字（可以为数组）
     * key:缓存数据使用的key。【可以指定，默认是参数值】。默认使用方法参数的值。使用SqEL表达式编写
     * keyGenerator:生成key的id（与key属性二选一）。他的值为配置类中注入bean中的名字
     * cacheManager:指定使用哪个缓存管理器(指定的值为config类里面的xxxCacheManager方法)
     * condition:符合改条件才可以缓存
     * unless:除非，unless条件为true时，不会缓存
     * sync:是否异步模式
     */

    /**
     * 【添加缓存】
     * 如果key存在，则不添加
     */
    @Override
    @Cacheable(/*,key="#root.methodName+'['+#id+']'"*/)
//    @Cacheable(cacheNames = {"employee"},keyGenerator = "keyGenerator")
    public Employee getById(Serializable id) {
        return super.getById(id);
    }

    /**
     * 【更新缓存】
     * 每次更新都会调用并写入缓存
     * 因为缓存的key是id，而不是对象，所以要指定key
     * 1.key = "#employee.id"
     * 2.key = "#result.id"也可以。（但是@Cacheable不可以用）
     */
    @Override
    @CachePut(key = "#employee.id")
    public boolean updateById(Employee employee) {
        return super.updateById(employee);
    }

    /**
     * 【清除缓存】
     * beforeInvocation=true 可以指定是否在方法全部完成之前执行（默认false，方法之后执行）
     * allEntries = true  删除所有缓存（无需指定key）
     * key = "#id"  删除指定key的缓存
     */
    @Override
    @CacheEvict(key = "#id")
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    /**
     * 【复杂的缓存注解】
     * 包含以上三种注解的数组
     */
    @Override
    @Caching(
            cacheable = {
                    @Cacheable(/*cacheNames = "emp",*/ key = "#lastName")
            },

            put = {
                    @CachePut(/*cacheNames = "emp",*/ key = "#result.id"),
                    @CachePut(/*cacheNames = "emp",*/ key = "#result.email")
            },
            evict = {

            }
    )
    public Employee getEmpByLastName(String lastName) {
        return employeeMapper.getEmpByLastName(lastName);
    }
}




